%{
#include "EnergyProxy.hpp"
%}

namespace kuai { namespace suan {

	class EnergyProxy
	{
	public:
		virtual ~EnergyProxy();
		virtual bool prepare(PyObject* self, PyObject* model) = 0;
	};	
	class ForceFieldEnergyProxy
		: public EnergyProxy
	{
	public:
		virtual bool prepare(PyObject* self, PyObject* model);
	};

	class NonbondEnergyProxy
		: public ForceFieldEnergyProxy
	{
	public:
		virtual bool prepare(PyObject* self, PyObject* model);
	};

	void screenPairList(PyObject* filter, PyObject* fffunc, int rank);

} }


%{

namespace kuai { namespace suan {

	extern bool convertToEnergySet(PyObject* model, PyObject* efunc, EnergySet& eset) {

		Py_ssize_t n = PySequence_Size(efunc);
		if (n < 0) {
			return false;
		}
		
		boost::tuple<PyObject*, XYZ*, size_t> coords = getXYZArray(model, "coords");
		if (boost::get<0>(coords) == NULL) {
			return false;
		}
		eset.nAtoms = boost::get<2>(coords);
		Py_DECREF(boost::get<0>(coords));

		bool result = true;
		for (Py_ssize_t  i = 0; i < n; ++i) {
			PyObject* funcI = PySequence_GetItem(efunc, i);
			assert (funcI != NULL);
			EnergyProxy* p;
			int isOK =  SWIG_ConvertPtr(funcI, (void**)(&p), SWIGTYPE_p_kuai__suan__EnergyProxy, 1);
			if (SWIG_IsOK(isOK)) {
				if (p->prepare(funcI, model)) {
					Py_DECREF(funcI);
					eset.funcs.push_back(p->func.get());
					continue;
				}
			}
			else {
				// TODO:
				PyErr_SetString(PyExc_NotImplementedError, "This function is in building");
			}
			Py_DECREF(funcI);
			result = false;
			break;
		}
		return result;
	}

	
} }
%}
